﻿﻿using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using WorldMapBase;
using WorldMapBase.Tile;
using WorldMapBase.Tile.Pool;
using WorldMapNew;
using Yoozoo.Managers.ResourceManagerV2.Framework.Resource;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Random = UnityEngine.Random;

public class TrafficSystem : MonoBehaviour
{
    ResLoader m_resLoader;
    Dictionary<int, MapChunckTrafficTileRunData> mapChunckTrafficDatas = new Dictionary<int, MapChunckTrafficTileRunData>();// 运行时配置数据 <地图块resId,数据>
    Dictionary<int, MapChunckTrafficRunData> mapChunckTrafficRunDatas = new Dictionary<int, MapChunckTrafficRunData>();// 运行时地图对象数据 <地图块tileIdx,数据>
    // temp
    // 地图块id 对应 地图交通数据配置路径映射 TODO可写入地图数据中
    Dictionary<int, string> mapChunckTrafficDataPaths = new Dictionary<int, string>() { 
   
    };
    // 小车资源id 
    List<int> mapChunckTrafficCarResIds = new List<int>() { 
        33,34,35
    };
    // const
    float carCheckInterval = 0.06f;// 小车检测碰撞间隔 
    float carCheckTime = -1;
    public bool isDebug = false; // 是否是debug模式
    public float[] lightTime = { 8, 10, 16 };

    // 小车性能相关
    static bool isCarCheck = true; // 是否检测小车碰撞 舍弃
    public int carNum = -1;// 小车限制数量 -1 不限制 按照地图块交通数据最大路线生成 

    public float checkLightTime = 0; // 红绿灯检测间隔

    public bool isOn = true;
    public bool isEnable = true;
    public void Init()
    {
        m_resLoader = ResLoader.Alloc();
        // 加载地图块交通数据
        foreach (int resId in mapChunckTrafficDataPaths.Keys)
        {
            string path = mapChunckTrafficDataPaths[resId];
            var hasAssetResult = UMTResource.HasAsset(path); // 检查一下data存在
            if (hasAssetResult != HasAssetResult.NotExist)
            {
                m_resLoader.Add2Load(path, (success, path1, asset) =>
                {
                    if (success)
                    {
                        MapChunckTrafficData data = asset as MapChunckTrafficData;
                        MapChunckTrafficTileRunData runData = new MapChunckTrafficTileRunData();
                        runData.trafficNodeDatas = new Dictionary<int, Dictionary<int, MapChunckTrafficPointRunData>>();
                        runData.trafficLightDatas = new Dictionary<int, List<TrafficLightData>>();
                        runData.trafficLineDatas = data.trafficLineDatas;
                        // 解析路点 将list数据解析成Dictionary
                        for (int i = 0; i < data.trafficNodeDatas.Count; i++)
                        {
                            // 路点 - 坐标点 - 中间点
                            TrafficNodeData nodeData = data.trafficNodeDatas[i];
                            Dictionary<int, MapChunckTrafficPointRunData> pointDatas = new Dictionary<int, MapChunckTrafficPointRunData>();
                            for (int ii = 0; ii < nodeData.trafficPointDatas.Count; ii++)
                            {
                                MapChunckTrafficPointRunData pointRunData = new MapChunckTrafficPointRunData();

                                TrafficPointData pointData = nodeData.trafficPointDatas[ii];
                                pointRunData.pointId = pointData.pointId;
                                pointRunData.pointVec3 = pointData.pointVec;
                                if (pointData.roadPointDatas.Count > 0)
                                {
                                    pointRunData.roadPointDatas = new Dictionary<int, TrafficRoadPointData>();
                                    for (int iii = 0; iii < pointData.roadPointDatas.Count; iii++)
                                    {
                                        TrafficRoadPointData roadPoint = pointData.roadPointDatas[iii];
                                        pointRunData.roadPointDatas[roadPoint.lineId] = roadPoint;
                                    }
                                }
                                pointDatas[pointRunData.pointId] = pointRunData;
                            }
                            runData.trafficNodeDatas[nodeData.nodeId] = pointDatas;
                            // 路灯数据
                            List<TrafficLightData> lightDatas = nodeData.trafficLightDatas;
                            runData.trafficLightDatas[nodeData.nodeId] = lightDatas;
                        }
                        mapChunckTrafficDatas[resId] = runData;
                    }
                });
            }
        }
        m_resLoader.Load();
    }

    public void DisPose()
    {
        m_resLoader.Recycle2Cache();
        m_resLoader = null;
        mapChunckTrafficDatas.Clear();
    }

    public void OnUpdate()
    {
        if (!isOn || !isEnable)
        {
            return;
        }
        if (mapChunckTrafficRunDatas == null || mapChunckTrafficRunDatas.Count <= 0) return;

        Vector4 cameraCorner = WorldCameraManager.GetInstance().GetCameraCorner();
        float deltaTime = Time.deltaTime;
        foreach (int key in mapChunckTrafficRunDatas.Keys)
        {
            var runData = mapChunckTrafficRunDatas[key];
            if (checkLightTime >= 1)
            {
                checkLightTime = 0;
                UpdateLightState(runData, 1);
                UpdateLightShow(runData, cameraCorner);
            }
            else
            {
                checkLightTime += deltaTime;
            }
            UpdateCar(runData, UpdateCarCheck(),cameraCorner,deltaTime);
        }
    }

    public bool isInCamera(Vector4 cameraCorner, Vector3 position)
    {
        if (position.x < cameraCorner.x)
            return false;
        if (position.x > cameraCorner.z)
            return false;
        if (position.z < cameraCorner.y)
            return false;
        if (position.z > cameraCorner.w)
            return false;
        return true;
    }
    // 新建地图块交通
    public void CreateChunckTraffic(int tileIdx)
    {
        if (!isEnable)
        {
            return;
        }
        int resId = WorldMapConfigData.GetTileResId(1, tileIdx, out int tileSize);// 取lod1的地图块资源id
        if (mapChunckTrafficDatas.ContainsKey(resId) == false || mapChunckTrafficRunDatas.ContainsKey(tileIdx)) return; // 没有数据 退出
        Vector3 offset = GetTileOffset(tileIdx);
        MapChunckTrafficTileRunData data = mapChunckTrafficDatas[resId];
        MapChunckTrafficRunData runData = new MapChunckTrafficRunData();
        runData.tileData = data;
        // 获取配置添加路灯
        runData.lights = new Dictionary<int, TrafficObject>();
        foreach (int nodeId in data.trafficLightDatas.Keys)
        {
            var lightDatas = data.trafficLightDatas[nodeId];
            for (int i = 0; i < lightDatas.Count; i++)
            {
                TrafficLightData lightData = lightDatas[i];
                TrafficObject trafficLight = AddTraffic(1, WorldEntry.TRAFFIC_LAYER_ID, lightData.lightData.resID);
                trafficLight.SetPosition(lightData.lightData.position + offset);
                trafficLight.SetRotation(lightData.lightData.rotation);
                trafficLight.SetScale(lightData.lightData.scale);
                int direction = lightData.controlRoadId1 * 10 + lightData.controlRoadId2;
                trafficLight.light.state = -1;
                trafficLight.light.nodeId = nodeId;
                trafficLight.light.direction = direction;
                //trafficLight.light.UpdateState();
                runData.lights[nodeId * 100 + direction] = trafficLight;
                runData = AddLightState(runData, nodeId, lightData.controlRoadId1, lightData.controlRoadId2);
            }
        }

        // 生成和线路等量的小车
        runData.cars = new List<TrafficObject>();
        for (int i = 0;i < data.trafficLineDatas.Count; i++)
        {
            if (carNum >= 0 && i >= carNum) break;
            int resIdx = Random.Range(0, mapChunckTrafficCarResIds.Count);
            int carResId = mapChunckTrafficCarResIds[resIdx];
            TrafficObject trafficCar = AddTraffic(1, WorldEntry.TRAFFIC_LAYER_ID,carResId);
            // 路线
            TrafficLineDataOne lineData = data.trafficLineDatas[i];
            trafficCar.car.isDebug = isDebug;
            trafficCar.car.SetMapChunckLineRunData(data, lineData, offset, tileIdx);
            runData.cars.Add(trafficCar);
        }
        mapChunckTrafficRunDatas[tileIdx] = runData;
    }

    public TrafficObject AddTraffic(int lodIndex, int mapLayer, int resID)
    { 
        TrafficObject obj = WorldPoolManager.GetWorldObject(lodIndex, mapLayer, resID) as TrafficObject;
        return obj;
    }

    // 移除地图块交通
    public void RemoveChunckTraffic(int tileIdx,bool bRemoveData = true)
    {
        if (mapChunckTrafficRunDatas.ContainsKey(tileIdx))
        {
            MapChunckTrafficRunData runData = mapChunckTrafficRunDatas[tileIdx];
            // 移除所有路灯 
            foreach (var light in runData.lights.Values)
            {
                WorldPoolManager.RecoverItem(light);
            }
            // 移除小车
            for (int i = 0;i < runData.cars.Count;i++)
            {
                WorldPoolManager.RecoverItem(runData.cars[i]);
            }
            if (bRemoveData)
            {
                mapChunckTrafficRunDatas.Remove(tileIdx);
            }
        }
    }

    bool UpdateCarCheck()
    {
        bool bCheck = false;
        if (carCheckTime < 0 || carCheckTime >= carCheckInterval)
        {
            bCheck = true;
            carCheckTime = 0;
        }
        else
        {
            carCheckTime += Time.deltaTime;
        }
        return bCheck;
    }

    // 更新小车车运行
    private void UpdateCar(MapChunckTrafficRunData runData,bool bCheck,Vector4 cameraCorner,float deltaTime)
    {
        for (int i = 0; i < runData.cars.Count; i++)
        {
            var car = runData.cars[i];
            //if (bCheck && isCarCheck)
            //{
            //    bool inCamera = isInCamera(cameraCorner, car.GetRefTrans.position);
            //    car.car.CheckMove(inCamera,deltaTime);
            //}
            
            car.car.Move(deltaTime);
            
            
        }
    }

    // 更新信号灯状态
    private void UpdateLightShow(MapChunckTrafficRunData runData,Vector4 cameraCorner)
    {
        if (runData.lights != null)
        {
            foreach (var light in runData.lights.Values)
            {
                if (isInCamera(cameraCorner,light.GetRefTrans.position))
                {
                    float time = runData.lightState[light.light.nodeId][light.light.direction];
                    int state = GetLightStateByTime(time);
                    light.light.UpdateShow(state);
                }
               
            }
        }
    }
    // 获取信号灯状态
    public int GetLightState(int tileIdx, int nodeId, int sideId1, int sideId2)
    {
        int state = 0;
        if (mapChunckTrafficRunDatas.TryGetValue(tileIdx, out MapChunckTrafficRunData runData))
        {
            if (runData.lightState.TryGetValue(nodeId, out Dictionary<int, float> lightState))
            {
                int key = sideId1 * 10 + sideId2;
                if (lightState.TryGetValue(key, out float time))
                {
                    state = GetLightStateByTime(time);
                }
            }
        }

        return state;
    }

    Vector3 GetTileOffset(int tileIdx)
    {
        Vector3 offset = Vector3.zero;
        var mapData = WorldMapConfigData.GetMapData();
        int mapSize = mapData.mapWidth;
        int tileSize = WorldEntry.m_iTileSize;
        int lineNum = mapSize / tileSize;
        offset.x = (tileIdx % lineNum + 0.5f) * tileSize;
        offset.z = (tileIdx / lineNum + 0.5f) * tileSize;
        return offset;
    }

    // 添加信号灯状态
    MapChunckTrafficRunData AddLightState(MapChunckTrafficRunData runData, int nodeId, int sideId1, int sideId2)
    {
        if (runData.lightState == null) runData.lightState = new Dictionary<int, Dictionary<int, float>>();
        if (runData.lightState.ContainsKey(nodeId) == false) runData.lightState[nodeId] = new Dictionary<int, float>();
        Dictionary<int, float> lightStates = runData.lightState[nodeId];
        // 先判断有没有垂直方向
        float lightTime = 0; // 默认绿灯
        if (sideId1 == 1 || sideId2 == 1) // 1 - 3方向
        {
            lightTime = 0;
        }
        else
        {
            lightTime = 10;
        }
        lightStates[sideId1 * 10 + sideId2] = lightTime;
        runData.lightState[nodeId] = lightStates;
        return runData;
    }

    private List<int> tmpKeys = new List<int>(32);
    // 更新信号灯状态
    void UpdateLightState(MapChunckTrafficRunData runDatas,float deltaTime)
    {
        float maxTime = 16;// max = 8 + 2 + 6
        foreach (int nodeId in runDatas.lightState.Keys)
        {
            Dictionary<int, float> lightStates = runDatas.lightState[nodeId];
            tmpKeys.Clear();
            tmpKeys.AddRange(lightStates.Keys);
            foreach (int direction in tmpKeys)
            {
                float time = lightStates[direction];
                time += deltaTime;
                time = time % maxTime;
                lightStates[direction] = time;
            }
        }
    }

    int GetLightStateByTime(float time)
    {
        int state = 0;
        float startTime = 0;
        for (int i = 0; i < lightTime.Length; i++)
        {
            if (time >= startTime && time < lightTime[i])
            {
                state = i;
                break;
            }
            startTime = lightTime[i];
        }
        return state;
    }

    // ================================ 性能分层 ================================
    
    //  设置小车每块最大上限 -1代表没有限制
    public void setCarNum(int num)
    {
        carNum = num;
    }

    // 设置小车检测碰撞开关
    public void setCarCheck(bool value)
    { 
        isCarCheck = value;
    }

    public static bool IsCarCheck => isCarCheck;

    public void setCarEnable(bool value)
    {
        if (value != isEnable)
        {
            isEnable = value;
            if (isEnable)
            {
                LODTileLayerListener plane = TileDisplayManager.Instance.GetTileLayerListener(WorldEntry.PLANE_LAYER_ID);
                if (plane != null)
                {
                    plane.OnAddMapAllCar();
                }
                
            }
            else 
            {
                if (mapChunckTrafficRunDatas == null || mapChunckTrafficRunDatas.Count <= 0) return;
                foreach (var tileIdx in mapChunckTrafficRunDatas.Keys)
                {
                    RemoveChunckTraffic(tileIdx,false);
                }
                mapChunckTrafficRunDatas.Clear();
            }
        }
    }
}